﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.IO;
using System.Reflection;
using System.IO.Compression;

namespace Learn.Web.MVC.Code.StaticCache
{
    public class StaticCacheAttribute : ActionFilterAttribute
    {
        private StringWriter writer;
        private TextWriter origin;
        private string key { get; set; }

        public int Duration { get; set; }
        public IStaticCache Cacher { get; set; }
        public string ContentType { get; set; }

        public StaticCacheAttribute()
        {
            Duration = 60;
            Cacher = StaticCacheHtml.Instance;
            ContentType = "text/html";

            this.Order = -1;
        }

        private TextWriter SwitchWriter(TextWriter writer)
        {
            var method = typeof(HttpResponse).GetMethod("SwitchWriter",
                BindingFlags.NonPublic| BindingFlags.Instance);

            return method.Invoke(HttpContext.Current.Response, new object[] { writer }) as TextWriter;
        }

        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            //var gzip = new GZipStream(filterContext.HttpContext.Response.Filter, CompressionMode.);
            key = filterContext.HttpContext.Request.RawUrl;
            var html = Cacher.Get<string>(key);
            if (string.IsNullOrEmpty(html))
            {
                writer = new StringWriter();
                origin = SwitchWriter(writer);
            }
            else
            {
                filterContext.Result = new EmptyResult();

                filterContext.HttpContext.Response.ContentType = ContentType;
                filterContext.HttpContext.Response.Write(html);
                filterContext.HttpContext.Response.Flush();
                filterContext.HttpContext.Response.End();
            }
        }

        public override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            if (writer != null)
            {
                writer.Flush();

                var html = writer.ToString();
                Cacher.Set(key,html,DateTime.Now.AddSeconds(60));

                SwitchWriter(origin);

                filterContext.HttpContext.Response.Write(html);
                filterContext.HttpContext.Response.Flush();
                filterContext.HttpContext.Response.End();
            }
        }
    }
}
